package cn.buk.qms.web;

import cn.buk.api.szkj.dto.eterm.response.RtpnrResponse;
import cn.buk.common.JsonResult;
import cn.buk.common.dto.CommonDto;
import cn.buk.common.dto.eterm.FfDto;
import cn.buk.common.dto.eterm.PnrDto;
import cn.buk.common.dto.eterm.PnrFlightDto;
import cn.buk.common.flight.dto.FlightInfoDto;
import cn.buk.common.flight.intl.response.IntlFlightResponseDto;
import cn.buk.common.sc.CommonSearchCriteria;
import cn.buk.flight.entity.FdRequest;
import cn.buk.flight.entity.FdResult;
import cn.buk.tms.dto.DetrInfoDto;
import cn.buk.tms.dto.TicketSaleDto;
import cn.buk.tms.entity.base.Airport;
import cn.buk.tms.entity.misc.DetrInfo;
import cn.buk.tms.entity.misc.FlightPriceCache;
import cn.buk.tms.sc.SearchTprCriteria;
import cn.buk.qms.service.*;
import cn.buk.tms.flight.service.EtermService;
import cn.buk.common.util.DateUtil;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static cn.buk.common.Constant.DATE_YYYY_MM_DD;
import static cn.buk.qms.HttpServletUtil.getIpAddr;

/**
 * @author yfdai
 * 2016-12-3
 */
@RestController
public class FlightController extends BaseController {

    private static final Logger logger = LogManager.getLogger(FlightController.class);

    @Autowired
    public FlightController(PnrService pnrService,
                            FlightPolicyService flightPolicyService,
                            FlightService flightService,
                            DetrService detrService,
                            FlightCharterService flightCharterService,
                            BasicDataService basicDataService,
                            EtermService etermService) {
        this.pnrService = pnrService;
        this.flightPolicyService = flightPolicyService;
        this.flightService = flightService;
        this.detrService = detrService;
        this.flightCharterService = flightCharterService;
        this.basicDataService = basicDataService;
        this.etermService = etermService;
    }

    private final PnrService pnrService;

    private final FlightPolicyService flightPolicyService;

    private final FlightService flightService;

    private final DetrService detrService;

    private final FlightCharterService flightCharterService;

    private final BasicDataService basicDataService;

    private final EtermService etermService;


    @RequestMapping("/processPnrDetail.do")
    public PnrDto processPnrDetail(HttpServletRequest request,
                                   @RequestParam("pnrDetail") String pnrDetail,
                                   @RequestParam(value = "pnrMode", defaultValue = "0") final int pnrMode
                                   ) {
        final int enterpriseId = getEnterpriseId(request);
        final String username = getUsername(request);

        PnrDto pnrInfo = new PnrDto();

        if (pnrMode == 2) {
            pnrInfo.setRtktDetail(pnrDetail);
        } else {

            if (pnrDetail != null && pnrDetail.trim().length() == 6) {
                // 记录编码，调用接口导出记录编码内容

                RtpnrResponse response = etermService.rt(enterpriseId, username, pnrDetail.trim().toUpperCase());
                pnrDetail = response.getCode() == 1 ? response.getPnrInfo().getPnrDetail() : null;
            }

            pnrInfo.setPnrDetail(pnrDetail);

            Set<String> airportSet = new HashSet<>();
            for (PnrFlightDto flt : pnrInfo.getFlights()) {
                airportSet.add(flt.getFlight().getDport());
                airportSet.add(flt.getFlight().getAport());
            }

            //默认为国内
            pnrInfo.setType3(0);
            for (String threeCode : airportSet) {
                Airport airport = basicDataService.getAirportByCode(threeCode);
                if (airport == null) {
                    pnrInfo.setType3(-1);
                    break;
                }

                if (!"CN".equalsIgnoreCase(airport.getCountryCode())) {
                    // 国际机场
                    pnrInfo.setType3(1);
                    break;
                }
            }
        }

        try {
            pnrService.savePnrLog(enterpriseId, pnrInfo.getPnrNo(), pnrDetail, "分析PNR");
            logger.info("{}, {}, {}", enterpriseId, username, pnrInfo.getPnrNo());
        } catch (Exception ex) {
            logger.error(ex.getMessage());
        }

        return pnrInfo;
    }

    /**
     * 处理PNR内容中航班所属信息行，主要配合前端页面改期页面使用
     */
    @RequestMapping("/processPnrFlight")
    public PnrFlightDto processPnrFlight(@RequestParam("content") String content) {
        return PnrFlightDto.createPnrFlight(content);
    }

    @RequestMapping("/searchFlightPrice.do")
    public CommonDto<FlightPriceCache> searchFlightPriceCache(HttpServletRequest request,
                                            @ModelAttribute("sc") CommonSearchCriteria sc) {
        final int enterpriseId = getEnterpriseId(request);

        List<FlightPriceCache> priceCaches = flightPolicyService.searchFlightPriceCache(enterpriseId, sc);

        CommonDto<FlightPriceCache> dto = new CommonDto<>();
        dto.setDataList(priceCaches);
        dto.setPage(sc.getPage());


        return dto;
    }


    @RequestMapping("/searchPriceRequest.do")
    public CommonDto<FdRequest> searchPriceRequest(HttpServletRequest request,
                                                   @ModelAttribute("sc") CommonSearchCriteria sc) {
        final int enterpriseId = getEnterpriseId(request);

        List<FdRequest> fdRequests = flightService.searchFdRequest(enterpriseId, sc);

        CommonDto<FdRequest> commonDto = new CommonDto<>();
        commonDto.setDataList(fdRequests);
        commonDto.setPage(sc.getPage());

        return commonDto;
    }

    @RequestMapping("/deleteAllFdRequest.do")
    public JsonResult deleteAllFdRequest(HttpServletRequest request) {
        final int enterpriseId = getEnterpriseId(request);

        JsonResult jsonResult = new JsonResult();

        int retCode = flightService.deleteAllPriceRequest(enterpriseId);

        if (retCode >= 0) {
            jsonResult.setStatus("OK");
            jsonResult.setErrmsg("成功删除 " + retCode + " 条数据.");
        } else {
            jsonResult.setStatus("ER");
            jsonResult.setErrmsg("操作失败");
        }

        return jsonResult;
    }

    @RequestMapping("/createPriceRequest.do")
    public JsonResult createPriceRequest(HttpServletRequest request,
                                         @RequestParam("carrier") String carrier,
                                         @RequestParam("dport") String dport,
                                         @RequestParam("aport") String aport,
                                         @RequestParam("ddate") String ddate
                                         ) {
        final int enterpriseId = getEnterpriseId(request);
        return flightService.createPriceRequest(enterpriseId, carrier, dport, aport, ddate);
    }

    /**
     * 通过上传excel文件，生成运价下载请求
     */
    @PostMapping(value = "/fd-request/excel")
    public JsonResult createPriceRequestByExcel(HttpServletRequest request,
                                                MultipartFile upfile) {
        final int enterpriseId = getEnterpriseId(request);

        //Now do something with file...
        String fileName = new String(upfile.getOriginalFilename().getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

        String filePath = System.getProperty("java.io.tmpdir");
        File outputFile = new File(filePath + fileName);
        try {
            FileCopyUtils.copy(upfile.getBytes(), outputFile);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return flightService.createPriceRequestByExcel(enterpriseId, filePath + fileName);
    }

    @RequestMapping("/deleteFdRequest.do")
    public JsonResult deleteFdRequest(HttpServletRequest request,
                                  @RequestParam("id") int id) {
        final int enterpriseId = getEnterpriseId(request);

        JsonResult jsonResult = new JsonResult();

        int retCode = flightService.deletePriceRequest(enterpriseId, id);

        if (retCode >= 0) {
            jsonResult.setStatus("OK");
            jsonResult.setErrmsg("成功删除 " + retCode + " 条数据.");
        } else {
            jsonResult.setStatus("ER");
            jsonResult.setErrmsg("失败");
        }

        return jsonResult;
    }

    @RequestMapping("/searchFdResult.do")
    public CommonDto<FdResult> searchFdResult(HttpServletRequest request,
                                              @ModelAttribute("sc") CommonSearchCriteria sc) {
        final int enterpriseId = getEnterpriseId(request);

        List<FdResult> fdResults = flightService.searchFdResult(enterpriseId, sc);

        CommonDto<FdResult> commonDto  = new CommonDto<>();
        commonDto.setDataList(fdResults);
        commonDto.setPage(sc.getPage());

        return commonDto;
    }

    @RequestMapping("/deleteFdResults")
    public JsonResult deleteAllFdResult(HttpServletRequest request) {
        final int enterpriseId = getEnterpriseId(request);
        int retCode = flightService.deleteAllPriceResult(enterpriseId);
        JsonResult jsonResult = JsonResult.createJsonResult(retCode);
        if (retCode == 0) {
            jsonResult.setErrmsg("没有删除任何数据");
        } else if (retCode > 0) {
            jsonResult.setDesc("已删除 " + retCode + " 条记录");
        }

        return jsonResult;
    }

    @RequestMapping("/downloadFdResult.do")
    public void downloadFdResult(HttpServletRequest request, HttpServletResponse response,
                                 @ModelAttribute("sc") CommonSearchCriteria sc) {
        final int enterpriseId = getEnterpriseId(request);

        //输出
        PrintWriter out;
        try {
            String filename = "fD-result-" + DateUtil.formatDate(DateUtil.getCurDateTime(), "yyyyMMddHHmmss") + ".csv";
            response.setHeader("Content-Disposition", "inline; filename=" + filename);
            response.setContentType("application/octet-stream");
//            ContentType.APPLICATION_OCTET_STREAM


            response.getOutputStream().write(
                    new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF});
            out = new PrintWriter(new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8));

            StringBuilder sb = FdResult.exportHeaderToStringBuffer();
            out.print(sb);
            out.flush();

            //begin searching data
            int pageNo = 1;
            boolean more = true;
            List<FdResult> fdResults;
            while (more) {
                more = false;

                sc.getPage().setPageNo(pageNo);
                sc.getPage().setPageSize(1000);

                fdResults = flightService.searchFdResult(enterpriseId, sc);

                for (FdResult fdResult : fdResults) {
                    if (DateUtil.getPastDays(fdResult.getLastupdate()) > 10) {
                        continue;
                    }

                    sb = fdResult.exportContentToStringBuffer();
                    out.print(sb);
                }
                out.flush();

                if (sc.getPage().getPageTotal() > pageNo) {
                    pageNo++;
                    more = true;
                }
            }

            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 通过上传excel文件，生成DETR票号
     */
    @PostMapping(value = "/detr-request/excel")
    public JsonResult createDetrRequestByExcel(HttpServletRequest request,
                                                MultipartFile upfile) {
        final int enterpriseId = getEnterpriseId(request);

        //Now do something with file...
        String fileName = new String(upfile.getOriginalFilename().getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

        String filePath = System.getProperty("java.io.tmpdir");
        File outputFile = new File(filePath + fileName);
        try {
            FileCopyUtils.copy(upfile.getBytes(), outputFile);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return detrService.createDetrRequestByExcel(enterpriseId, filePath + fileName);
    }

    @RequestMapping("/searchDetr.do")
    public CommonDto<DetrInfoDto> searchDetrResult(HttpServletRequest request,
                                              @ModelAttribute("sc") CommonSearchCriteria sc) {
        final int enterpriseId = getEnterpriseId(request);

        List<DetrInfoDto> fdResults = detrService.searchDetrInfos(enterpriseId, sc);

        CommonDto<DetrInfoDto> commonDto  = new CommonDto<>();
        commonDto.setDataList(fdResults);
        commonDto.setPage(sc.getPage());

        return commonDto;
    }

    @RequestMapping("/detr/refresh")
    public JsonResult refreshDetrResult(HttpServletRequest request,
        @RequestParam("id") final int id) {
        final int enterpriseId = getEnterpriseId(request);

        return detrService.refreshDetrInfo(enterpriseId, id);

    }

    @RequestMapping("/downloadDetr.do")
    public void downloadDetrs(HttpServletRequest request, HttpServletResponse response,
                                 @ModelAttribute("sc") CommonSearchCriteria sc) {
        final int enterpriseId = getEnterpriseId(request);

        //输出
        PrintWriter out;
        try {
            String filename = "detr-" + DateUtil.formatDate(DateUtil.getCurDateTime(), "yyyyMMddHHmmss") + ".csv";
            response.setHeader("Content-Disposition", "inline; filename=" + filename);
            response.setContentType("application/octet-stream");

            // 加上UTF-8文件的标识字符
            response.getOutputStream().write(
                    new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF});
            out = new PrintWriter(new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8));

            StringBuilder sb = DetrInfo.exportHeaderToStringBuffer();
            out.print(sb);
            out.flush();

            //begin searching data
            int pageNo = 1;
            boolean more = true;
            List<DetrInfoDto> infos = null;

            while (more) {
                more = false;

                sc.getPage().setPageNo(pageNo);
                sc.getPage().setPageSize(1000);

                infos = detrService.searchDetrInfos(enterpriseId, sc);

                for (DetrInfoDto info : infos) {
                    //TODO 下载具体的DETR内容 yfdai 2021-10-21
//                    sb = info.exportContentToStringBuffer();
                    out.print(sb);
                }
                out.flush();

                if (sc.getPage().getPageTotal() > pageNo) {
                    pageNo++;
                    more = true;
                }
            }

            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 保存TPR内容
     * @param tprContent TPR指令全部内容
     * @param tprDate TPR 日期
     * @param deviceId 打票机ID
     */
    @PostMapping(value = "/tpr/content")
    public JsonResult createTprInfo(HttpServletRequest request,
                                    @RequestParam(value = "tprContent", required = false) String tprContent,
                                    @RequestParam(value="tprDate", required = false)
                                        @DateTimeFormat(pattern="yyyy-MM-dd") final Date tprDate,
                                    @RequestParam(value="deviceId", defaultValue = "1") final int deviceId) {
        final int enterpriseId = getEnterpriseId(request);
        final String username = getUsername(request);

        return flightCharterService.createTprInfoByContent(enterpriseId, username, tprContent, deviceId, tprDate);
    }

    /**
     *
     * @param ticketStatus 客票状态
     *                     -1 所有
     *                     0 正常票-出票
     *                     1 正常票-改签
     *                     4 退票
     * @param type3 国内国际
     *              0 - 国内
     *              1 - 国际
     * @param checkStatus 匹配状态
     *                    -1 所有
     *                    0 待匹配
     *                    2 已匹配
     */
    @GetMapping(value="/tprs")
    public CommonDto<TicketSaleDto> searchTprs(HttpServletRequest request,
                                               @RequestParam(value="beginDate", required = false) @DateTimeFormat(pattern="yyyy-MM-dd") final Date beginDate,
                                               @RequestParam(value="endDate", required = false) @DateTimeFormat(pattern="yyyy-MM-dd") final Date endDate,
                                               @RequestParam(value = "device", defaultValue = "0") final int deviceId,
                                               @RequestParam(value = "ticketStatus", defaultValue = "0") final int ticketStatus,
                                               @RequestParam(value = "type3", defaultValue = "-1") final int type3,
                                               @RequestParam(value = "checkStatus", defaultValue = "-1") final int checkStatus,
                                               @RequestParam(value = "ticketNo", required = false) String ticketNo,
                                               @RequestParam(value = "etermUsername", required = false) String etermUsername,
                                               @RequestParam(value = "pageSize", defaultValue = "1000") final int pageSize,
                                               @RequestParam(value = "pageNo", defaultValue = "1") final int pageNo) {
        final int enterpriseId = getEnterpriseId(request);
        final int userId = getUserId(request);

        SearchTprCriteria sc = new SearchTprCriteria();
        sc.setPageNo(pageNo);
        sc.setPageSize(pageSize);

        sc.setBeginDate(beginDate);
        sc.setEndDate(endDate);
        sc.setDeviceId(deviceId);
        sc.setType3(type3);
        sc.setCheckStatus(checkStatus);
        sc.setTicketStatus(ticketStatus + "");

        List<TicketSaleDto> list =  flightCharterService.searchTprs(enterpriseId, userId, etermUsername, ticketNo, sc);

        CommonDto<TicketSaleDto> tsDto = new CommonDto<>();
        tsDto.setDataList(list);
        tsDto.setPage(sc.getPage());

        return tsDto;
    }

    @GetMapping(value="/tprs/download")
    public void downloadTprs(HttpServletRequest request, HttpServletResponse response,
                             @RequestParam(value="beginDate", required = false) @DateTimeFormat(pattern="yyyy-MM-dd") final Date beginDate,
                             @RequestParam(value="endDate", required = false) @DateTimeFormat(pattern="yyyy-MM-dd") final Date endDate,
                             @RequestParam(value = "device", defaultValue = "0", required = false) final int deviceId,
                             @RequestParam(value = "ticketStatus", defaultValue = "0", required = false) final int ticketStatus,
                             @RequestParam(value = "etermUsername", required = false) String etermUsername
                             ) {
        final int enterpriseId = getEnterpriseId(request);
        final int userId = getEnterpriseId(request);

        SearchTprCriteria sc = new SearchTprCriteria();
        sc.setPageNo(1);
        sc.setPageSize(2000 * 40);

        sc.setBeginDate(beginDate);
        sc.setEndDate(endDate);
        sc.setDeviceId(deviceId);
        sc.setTicketStatus(ticketStatus + "");

        List<TicketSaleDto> list = flightCharterService.searchTprs(enterpriseId, userId, etermUsername, null, sc);

        //输出
        PrintWriter out;
        try {
            String filename = "tpr-result-" + DateUtil.formatDate(DateUtil.getCurDateTime(), "yyyyMMddHHmmss") + ".csv";
            response.setHeader("Content-Disposition", "inline; filename=" + filename);
            response.setContentType("application/octet-stream");

            response.getOutputStream().write(
                    new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF});
            out = new PrintWriter(new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8));

            StringBuilder sb = TicketSaleDto.exportTitle();
            out.print(sb);
            out.flush();

            //begin searching data
            for (TicketSaleDto info : list) {
                sb = info.exportContent();
                out.print(sb);
            }
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }



    @RequestMapping(value = {"/rav", "/flights/rav"}, produces = {"application/json"})
    public CommonDto<FlightInfoDto> rav(HttpServletRequest request,
                                                 @RequestParam(value = "dcity") final String dcity,
                                                 @RequestParam(value = "acity") final String acity,
                                                 @RequestParam(value = "ddate") final String ddate,
                                                 @RequestParam(value = "source", defaultValue = "1") final int source,
                                                 @RequestParam(value = "startPosition", defaultValue = "-1") final int startPosition
    )  {
        final int enterpriseId = getEnterpriseId(request);
        final String username = getUsername(request);
        final String remoteAddr = getIpAddr(request);

        Date ddate0;

        try {
            ddate0 = DateUtil.convertToDate(ddate, DATE_YYYY_MM_DD);
        } catch (ParseException e) {
            ddate0 = DateUtil.getTomorrowDate();
        }

        return flightService.searchFlight(enterpriseId, username, dcity, acity, ddate0, source, remoteAddr);
    }

    /**
     * 查找航班的经停信息
     * @param request 用户获取会话信息
     * @param flightNo 航班号
     * @param ddate 航班日期
     * @return FF指令结果
     */
    @GetMapping("/flight/stopover")
    public FfDto searchFlightStopover(HttpServletRequest request,
                                      @RequestParam(value = "flightNo") final String flightNo,
                                      @RequestParam(value = "ddate") final String ddate
    )  {
        return flightService.searchFlightStopover(getEnterpriseId(request), flightNo, ddate);
    }

    /**
     * 国际机票查找
     */
    @RequestMapping(value = {"/searchOne"}, produces = {"application/json"})
    public IntlFlightResponseDto searchOne(HttpServletRequest request,
                                           @RequestParam(value = "routeType") final int routeType,
                                           @RequestParam(value = "dcity") final String dcity,
                                           @RequestParam(value = "acity") final String acity,
                                           @RequestParam(value = "ddate") final String ddate,
                                           @RequestParam(value = "adate") final String adate
    )  {
        final int enterpriseId = getEnterpriseId(request);
        final String remoteAddr = getIpAddr(request);
        logger.debug("remote address: " + remoteAddr);

        Date ddate0;

        try {
            ddate0 = DateUtil.convertToDate(ddate, DATE_YYYY_MM_DD);
        } catch (ParseException e) {
            ddate0 = DateUtil.getTomorrowDate();
        }

        Date adate0 = null;

        try {
            if (adate != null) {
                adate0 = DateUtil.convertToDate(adate, DATE_YYYY_MM_DD);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }

        return flightService.searchIntlFlight(enterpriseId, routeType, dcity, acity, ddate0, adate0, remoteAddr, null);
    }

    /**
     * 执行黑屏指令
     */
    @RequestMapping(value="/eterm")
    public JsonResult execEtermCmd(HttpServletRequest request,
                                   @RequestParam(value = "hostcmd") final String hostcmd,
                                   @CookieValue(value = "openid", required = false) String openid) {
        final int enterpriseId = getEnterpriseId(request);
        final String remoteAddr = getIpAddr(request);
        logger.info("remote address: " + remoteAddr + ", " + hostcmd + ", " + openid);

        return flightService.execEtermCmd(enterpriseId, hostcmd, openid);
    }
}
